Skip to content

Add LUKS disk encryption support for Linux OS morphing#436

Merged
petrutlucian94 merged 5 commits into
cloudbase:masterfrom
claudiubelu:luks-os-morphing
Jun 5, 2026
Merged

Add LUKS disk encryption support for Linux OS morphing#436
petrutlucian94 merged 5 commits into
cloudbase:masterfrom
claudiubelu:luks-os-morphing

Conversation

@claudiubelu

@claudiubelu claudiubelu commented May 22, 2026

Copy link
Copy Markdown
Member

The bulk of the work lives in the new LinuxLuksMixin class
(osmount/luks_mixin.py), which is then included in BaseLinuxOSMountTools:

  • mount_os(): check osmorphing_info["disk_luks_passphrases"] for each block device. confirmed LUKS containers are opened via cryptsetup luksOpen and the resulting /dev/mapper/<name> path is used in place of the raw device. dismount_os() closes them again after all filesystems have been unmounted.

  • remove_encryption_artifacts: after OS morphing, stale TPM2 LUKS tokens and their keyslots are killed and the corresponding tpm2-* options are stripped from /etc/crypttab. The source TPM does not exist on the destination, so leaving these in place would cause the initramfs to hang or fail on first boot.

  • install_encryption_firstboot_setup: a temporary migration keyfile is injected into the guest, /etc/crypttab is updated to reference it, the initramfs is rebuilt so the migrated VM can boot, GRUB is patched to use the crypttab mapper names instead of the osmount-time names, and a systemd one-shot service is installed to re-enroll TPM2 and remove the migration keyfile on the first boot of the destination VM.

The firstboot shell scripts live in coriolis/osmorphing/osmount/resources:

  • luks_firstboot_initramfs_tools.sh and targets update-initramfs-based systems (Debian / Ubuntu).
  • luks_firstboot_dracut.sh: targets dracut-based systems.

Note that the scripts include a reboot; a migration with LUKS-encrypted disks is not considered completed until a reboot is performed and the disks get unlocked and get mounted properly.

@claudiubelu claudiubelu force-pushed the luks-os-morphing branch 4 times, most recently from 33a3ef6 to 1e84389 Compare May 22, 2026 11:33
Comment thread coriolis/osmorphing/osmount/resources/luks_firstboot_dracut.sh
Comment thread coriolis/osmorphing/osmount/luks_mixin.py Outdated
Comment thread coriolis/osmorphing/osmount/luks_mixin.py Outdated
disk_id = os.path.basename(self._src_device)

# Write a minimal Linux OS on the device, encrypted with LUKS.
test_utils.make_luks_device(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Later on, it might be useful to test the scenario in which there are multiple disk attachments. We'd have to ensure that Coriolis doesn't error out if the user didn't specify the keys for secondary encrypted disks.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, but that is going to be more relevant in more complex tests, in which we actually spin up a replica and assert that the first boot scripts also worked as intended, and then we can also assert that additional disks are also accessible. Not much we can do here, in these tests specifically.

Comment thread coriolis/osmorphing/osmount/luks_mixin.py Outdated
Comment thread coriolis/osmorphing/osmount/luks_mixin.py Outdated
Comment thread coriolis/tests/integration/deployments/test_osmorphing.py Outdated
Comment thread coriolis/tests/integration/deployments/test_osmorphing.py Outdated
@claudiubelu claudiubelu force-pushed the luks-os-morphing branch 2 times, most recently from 8fb8340 to 3d99e52 Compare May 27, 2026 13:32
Comment thread coriolis/tests/integration/test_provider/imp.py Outdated
Comment thread coriolis/osmorphing/osmount/base.py Outdated
petrutlucian94 added a commit to petrutlucian94/coriolis that referenced this pull request Jun 3, 2026
Just like in case of LUKS (cloudbase#436),
we'll let Coriolis users specify a BitLocker recovery password.

At the very least it should unlock the OS volume, however it may
be used for other encrypted volumes as well. If no encrypted
volume could be unlocked using the specified key, Coriolis will
error out.

In addition to that, we'll temporarily suspend BitLocker on the
specified volumes. It won't decrypt the volumes, it merely adds a
publicly accessible protector that allows the replica instance to
boot.

Once the replica instance boots, BitLocker will be resumed automatically
and the TPM protector will be reconfigured.
petrutlucian94 added a commit to petrutlucian94/coriolis that referenced this pull request Jun 3, 2026
Just like in case of LUKS (cloudbase#436),
we'll let Coriolis users specify a BitLocker recovery password.

At the very least it should unlock the OS volume, however it may
be used for other encrypted volumes as well. If no encrypted
volume could be unlocked using the specified key, Coriolis will
error out.

In addition to that, we'll temporarily suspend BitLocker on the
specified volumes. It won't decrypt the volumes, it merely adds a
publicly accessible protector that allows the replica instance to
boot.

Once the replica instance boots, BitLocker will be resumed automatically
and the TPM protector will be reconfigured.
petrutlucian94 added a commit to petrutlucian94/coriolis that referenced this pull request Jun 3, 2026
Just like in case of LUKS (cloudbase#436),
we'll let Coriolis users specify a BitLocker recovery password.

At the very least it should unlock the OS volume, however it may
be used for other encrypted volumes as well. If no encrypted
volume could be unlocked using the specified key, Coriolis will
error out.

In addition to that, we'll temporarily suspend BitLocker on the
specified volumes. It won't decrypt the volumes, it merely adds a
publicly accessible protector that allows the replica instance to
boot.

Once the replica instance boots, BitLocker will be resumed automatically
and the TPM protector will be reconfigured.
@claudiubelu claudiubelu force-pushed the luks-os-morphing branch 2 times, most recently from 6f88988 to ac494de Compare June 5, 2026 08:44
Comment thread coriolis/osmorphing/osmount/resources/luks_firstboot_dracut.sh Outdated
Comment thread coriolis/osmorphing/osmount/resources/luks_firstboot_dracut.sh Outdated
Comment thread coriolis/osmorphing/osmount/resources/luks_firstboot_initramfs_tools.sh Outdated
Comment thread coriolis/osmorphing/osmount/base.py Outdated
Comment thread coriolis/osmorphing/osmount/luks_mixin.py Outdated
Comment thread coriolis/osmorphing/osmount/luks_mixin.py Outdated
The bulk of the work lives in the new `LinuxLUKSMixin` class
(`osmount/luks_mixin.py`), which is then included in `BaseLinuxOSMountTools`:

- `mount_os()`: check `osmorphing_info["encrypted_disks_passphrase"]` for each
  block device. confirmed LUKS containers are opened via `cryptsetup luksOpen`
  and the resulting `/dev/mapper/<name>` path is used in place of the raw device.
  `dismount_os()` closes them again after all filesystems have been unmounted.

- `remove_encryption_artifacts`: after OS morphing, stale TPM2 LUKS tokens and
  their keyslots are killed and the corresponding `tpm2-*` options are stripped
  from `/etc/crypttab`. The source TPM does not exist on the destination, so
  leaving these in place would cause the initramfs to hang or fail on first boot.

- `install_encryption_firstboot_setup`: a temporary migration keyfile is injected
  into the guest, `/etc/crypttab` is updated to reference it, the initramfs is
  rebuilt so the migrated VM can boot, GRUB is patched to use the crypttab mapper
  names instead of the osmount-time names, and a systemd one-shot service is
  installed to re-enroll TPM2 and remove the migration keyfile on the first boot
  of the destination VM.

The firstboot shell script itself lives in
`coriolis/osmorphing/osmount/resources/luks_firstboot_initramfs_tools.sh` and
targets `update-initramfs`-based systems (Debian / Ubuntu).
Extends `LinuxLuksMixin` with dracut support for RHEL / Fedora / SUSE guests:

- `_configure_dracut_keyfiles`: writes a `dracut.conf.d/99-coriolis-luks.conf`
  snippet that adds the migration keyfiles to `install_items`, ensuring dracut
  embeds them in the initramfs. It also probes for the
  `libcryptsetup-token-systemd-tpm2.so` plugin (checked against a list of
  known paths) and adds it explicitly, because cryptsetup loads TPM2 token
  plugins via `dlopen` and dracut's `ldd` analysis would otherwise miss it
  along with its `libtss2` dependencies.

- `_build_dracut_include_args`: returns `--include` args that force-embed
  `/etc/crypttab` and all `coriolis_*.key` keyfiles into the initramfs image.
  Without an explicit crypttab embed, dracut names the mapper `luks-<UUID>`
  rather than the crypttab name and cannot find the keyfile at boot.

- `luks_firstboot_dracut.sh`: the firstboot shell script for dracut-based systems.
  Runs once on first boot to re-enroll TPM2, remove the migration keyslots, and
  rebuild the initramfs so the embedded keyfile no longer ships in future initramfs
  images.
Adds `cryptsetup` to the `data-minion` Dockerfile. Required by osmount
LUKS unlock / lock; `cryptsetup` `luksOpen` / `luksClose` are called
over SSH on the morphing container.

Adds `make_luks_device` to `test_utils.py`: formats the device with LUKS,
opens it, writes a minimal Linux OS tree inside via make_os_device(),
then closes the mapper.

Adds integration test in which the source disk is LUKS-encrypted. The
test runs a full transfer + deployment with skip_os_morphing=False, and
asserts that it completed.
A previous commit introduced the ability to register replica first boot
scripts, which is something we also need for LUKS.

@petrutlucian94 petrutlucian94 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. We can merge it once the integration tests finish.

@petrutlucian94 petrutlucian94 merged commit 512459a into cloudbase:master Jun 5, 2026
5 checks passed
petrutlucian94 added a commit to petrutlucian94/coriolis that referenced this pull request Jun 5, 2026
Just like in case of LUKS (cloudbase#436),
we'll let Coriolis users specify a BitLocker recovery password.

At the very least it should unlock the OS volume, however it may
be used for other encrypted volumes as well. If no encrypted
volume could be unlocked using the specified key, Coriolis will
error out.

In addition to that, we'll temporarily suspend BitLocker on the
specified volumes. It won't decrypt the volumes, it merely adds a
publicly accessible protector that allows the replica instance to
boot.

Once the replica instance boots, BitLocker will be resumed automatically
and the TPM protector will be reconfigured.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants